import os
from datetime import datetime

from PIL import Image
from moviepy.editor import VideoFileClip


# 对抖音图文进行校验
def check_douyin_tuwen(data):
    # 1.对抖音图片进行校验
    image_paths_str = data.get("媒体")
    # 将图片路径字符串分割为列表
    image_paths = image_paths_str.split(';')

    # 设定规则参数
    MAX_SIZE_MB = 50
    ALLOWED_FORMATS = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp')  # 不包含'.gif'
    MAX_ASPECT_RATIO = 1 / 2
    MAX_IMAGE_COUNT = 35

    # 校验图片数量
    if len(image_paths) > MAX_IMAGE_COUNT:
        raise ValueError(f"图片数量超过最大限制，当前数量为{len(image_paths)}，最大允许数量为{MAX_IMAGE_COUNT}")

    # 遍历每个图片路径进行校验
    for image_path in image_paths:
        if not os.path.exists(image_path):
            print(f"{image_path}文件不存在")
        # 校验图片格式
        if not image_path.lower().endswith(ALLOWED_FORMATS):
            raise ValueError(f"图片格式不符合要求，文件路径：{image_path}")

        # 校验图片大小
        if os.path.getsize(image_path) > MAX_SIZE_MB * 1024 * 1024:
            raise ValueError(f"图片大小超过最大限制，文件路径：{image_path}")

        # 校验图片分辨率
        with Image.open(image_path) as img:
            width, height = img.size
            if width / height > MAX_ASPECT_RATIO or height / width > MAX_ASPECT_RATIO:
                print(f"建议宽高比不超过1:2，文件路径：{image_path}")
    # 2.对文本内容进行校验
    title = data.get("标题", "")
    desc = data.get("作品描述", "")
    if len(title) > 20:
        raise ValueError("标题最大20个字符")
    if len(title + desc) > 1000:
        raise ValueError("标题 + 作品描述字数不大于1000")
    # 3.检查封面
    cover = data.get("封面", "")
    if not os.path.isabs(cover) or not os.path.exists(cover):
        print(f"封面路径 {cover} 不存在或者没有设置封面")
    # 4.检查音乐
    music = data.get("音乐", "")
    if music is None or music == "":
        print(f"没有设置音乐")
    # 5.检查位置
    location = data.get("位置", "")
    if location is None or location == "":
        print(f"没有设置位置")
    # 5.检查热点
    hot_point = data.get("申请关联热点", "")
    if hot_point is None or hot_point == "":
        print(f"没有申请关联热点")
    # 6.检查允许他人保存图片
    save_list = ['允许', '不允许']
    save = data.get("允许他人保存图片")
    if save not in save_list:
        print("没有设置是否 允许他人保存图片 ,默认为允许")
    # 7.检查权限设置
    right_list = ['公开', '好友可见', '仅自己可见']
    right = data.get("权限设置", "")
    if right not in right_list:
        print("没有设置 权限设置 ,默认为公开")
    # 8.检查定时发布是否超出可用时间
    time_str = data.get("发布时间", "")
    if time_str == "":
        print("未设置发布时间,默认为立即发布")
    target_time = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
    current_time = datetime.now()
    time_diff = target_time - current_time
    if not (time_diff.total_seconds() > 7200 and time_diff.days <= 14):
        raise ValueError("指定定时时间不在允许范围,允许范围为(2h-14天)")
    print("抖音.图文校验完成")


# 对抖音视频进行校验
def check_douyin_video(data):
    # 1.对抖音视频进行校验
    video_path = data.get("媒体")
    # 检查文件是否存在
    if not os.path.exists(video_path):
        print(f"{video_path}文件不存在")
    # 支持的视频格式列表
    supported_formats = ['mp4', 'webm']

    # 获取视频文件的扩展名
    file_extension = os.path.splitext(video_path)[1][1:].lower()

    # 检查视频格式是否支持
    if file_extension not in supported_formats:
        raise ValueError(f"视频格式不支持。支持的格式有：{supported_formats}")
    # 获取视频文件的大小
    file_size = os.path.getsize(video_path)

    # 检查视频文件大小是否超过16G
    if file_size > 16 * 1024 ** 3:
        raise ValueError("视频文件大小超过16G。")
    # 使用moviepy获取视频属性
    clip = VideoFileClip(video_path)

    # 检查视频时长是否在60分钟以内
    if clip.duration > 3600:
        raise ValueError("视频时长超过60分钟。")
    # 获取视频分辨率
    video_resolution = clip.size
    width, height = video_resolution

    # 检查视频分辨率是否为720p及以上
    if width < 720 or height < 1280:
        print("建议视频分辨率不低于720p，码率10Mbps以内")
        # raise ValueError("视频分辨率低于720p（1280x720）")
    print("视频校验通过：格式、大小、时长和分辨率均符合要求。")
    # 释放资源
    clip.close()
    # 2.对文本内容进行校验
    title = data.get("标题", "")
    desc = data.get("作品描述", "")
    if len(title) > 30:
        raise ValueError("标题最大30个字符")
    if len(desc) > 1000:
        raise ValueError("作品描述字数不大于1000")
    # 3.检查封面
    cover = data.get("封面", "")
    if not os.path.isabs(cover) or not os.path.exists(cover):
        raise ValueError(f"封面路径 {cover} 不存在或者没有设置封面")
    # 4.检查音乐
    music = data.get("音乐", "")
    if music is None or music == "":
        print(f"没有设置音乐")
    # 5.检查位置
    location = data.get("位置", "")
    if location is None or location == "":
        print(f"没有设置位置")
    # 5.检查热点
    hot_point = data.get("申请关联热点", "")
    if hot_point is None or hot_point == "":
        print(f"没有申请关联热点")
    # 6.检查允许他人保存图片
    save_list = ['允许', '不允许']
    save = data.get("允许他人保存图片")
    if save not in save_list:
        print("没有设置是否 允许他人保存图片 ,默认为允许")
    # 7.检查权限设置
    right_list = ['公开', '好友可见', '仅自己可见']
    right = data.get("权限设置", "")
    if right not in right_list:
        print("没有设置 权限设置 ,默认为公开")
    # 8.检查定时发布是否超出可用时间
    time_str = data.get("发布时间", "")
    if time_str == "":
        print("未设置发布时间,默认为立即发布")
    target_time = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
    current_time = datetime.now()
    time_diff = target_time - current_time
    if not (time_diff.total_seconds() > 7200 and time_diff.days <= 14):
        raise ValueError("指定定时时间不在允许范围,允许范围为(2h-14天)")
    print("抖音.视频校验完成")


# 计算小红书标题长度
def calculate_string_length(s):
    length = 0
    for char in s:
        if '\u4e00' <= char <= '\u9fff':  # 判断是否为中文字符
            length += 1
        else:
            length += 0.5
    return length


# 对小红书图文进行校验
def check_xiaohonshu_tuwen(data):
    # 1.对小红书图片进行校验
    image_paths_str = data.get("媒体")
    # 将图片路径字符串分割为列表
    image_paths = image_paths_str.split(';')

    # 设定规则参数
    MAX_SIZE_MB = 20
    ALLOWED_FORMATS = ('.jpg', '.jpeg', '.png', '.webp')
    MAX_ASPECT_RATIO = 3 / 4
    MAX_IMAGE_COUNT = 18

    # 校验图片数量
    if len(image_paths) > MAX_IMAGE_COUNT:
        raise ValueError(f"图片数量超过最大限制，当前数量为{len(image_paths)}，最大允许数量为{MAX_IMAGE_COUNT}")

    # 遍历每个图片路径进行校验
    for image_path in image_paths:
        # 检查文件是否存在
        if not os.path.exists(image_path):
            print(f"{image_path}文件不存在")
        # 校验图片格式
        if not image_path.lower().endswith(ALLOWED_FORMATS):
            raise ValueError(f"图片格式不符合要求，文件路径：{image_path}")

        # 校验图片大小
        if os.path.getsize(image_path) > MAX_SIZE_MB * 1024 * 1024:
            raise ValueError(f"图片大小超过最大限制，文件路径：{image_path}")

        # 校验图片分辨率
        with Image.open(image_path) as img:
            width, height = img.size
            if width / height > MAX_ASPECT_RATIO or height / width > MAX_ASPECT_RATIO:
                print(f"建议宽高比不超过3:4，文件路径：{image_path}")
            # 图片分辨率 这里低于也可以用但是效果不好
            if width < 720 or height < 960:
                raise ValueError("图片分辨率太低,可能影响显示效果")
    # 2.对文本内容进行校验
    title = data.get("标题", "")
    desc = data.get("作品描述", "")
    if calculate_string_length(title) > 20:
        raise ValueError("标题最大20个字符")
    if len(desc) > 1000:
        raise ValueError("作品描述字数不大于1000")
    # 3.检查位置
    location = data.get("位置", "")
    if location is None or location == "":
        print(f"没有设置位置")
    # 4.检查权限设置
    right_list = ['公开', '仅自己可见']
    right = data.get("权限设置", "")
    if right not in right_list:
        print("没有设置 权限设置 ,默认为公开")
    # 8.检查定时发布是否超出可用时间
    time_str = data.get("发布时间", "")
    if time_str == "":
        print("未设置发布时间,默认为立即发布")
    target_time = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
    current_time = datetime.now()
    time_diff = target_time - current_time
    if not (time_diff.total_seconds() > 3600 and time_diff.days <= 14):
        raise ValueError("指定定时时间不在允许范围,允许范围为(1h-14天)")
    print("小红书.图文校验完成")
    pass


# 对小红书视频进行校验
def check_xiaohonshu_video(data):
    # 1.对小红书视频进行校验
    video_path = data.get("媒体")
    # 检查文件是否存在
    if not os.path.exists(video_path):
        print(f"{video_path}文件不存在")
    # 支持的视频格式列表
    supported_formats = ['mp4', 'mov']  # 更新支持的视频格式列表

    # 获取视频文件的扩展名
    file_extension = os.path.splitext(video_path)[1][1:].lower()

    # 检查视频格式是否支持
    if file_extension not in supported_formats:
        raise ValueError(f"视频格式不支持。推荐的格式有：{supported_formats}")

    # 获取视频文件的大小
    file_size = os.path.getsize(video_path)

    # 检查视频文件大小是否超过10GB
    if file_size > 10 * 1024 ** 3:
        raise ValueError("视频文件大小超过10GB。")

    # 使用moviepy获取视频属性
    clip = VideoFileClip(video_path)

    # 检查视频时长是否在15分钟以内
    if clip.duration > 15 * 60:
        raise ValueError("视频时长超过15分钟。")

    # 获取视频分辨率
    video_resolution = clip.size
    width, height = video_resolution

    # 检查视频分辨率是否为720p及以上
    if width < 720 or height < 1280:
        raise ValueError("视频分辨率低于720p（1280x720）。")

    # 如果有额外的要求检查视频分辨率是否超过1080p，可以添加以下代码
    # 检查视频分辨率是否超过1080p，这部分代码仅作为参考，根据实际情况使用
    if width > 1920 or height > 1080:
        print("警告：超过1080P的视频建议用网页端上传以保证画质更清晰。")
    else:
        print("视频分辨率适中，适合上传。")

    print("视频校验通过：格式、大小、时长和分辨率均符合要求。")

    # 释放资源
    clip.close()

    # 2.对文本内容进行校验
    title = data.get("标题", "")
    desc = data.get("作品描述", "")
    if calculate_string_length(title) > 20:
        raise ValueError("标题最大20个字符")
    if len(desc) > 1000:
        raise ValueError("作品描述字数不大于1000")
    # 3.检查位置
    location = data.get("位置", "")
    if location is None or location == "":
        print(f"没有设置位置")
    # 4.检查权限设置
    right_list = ['公开', '仅自己可见']
    right = data.get("权限设置", "")
    if right not in right_list:
        print("没有设置 权限设置 ,默认为公开")
    # 8.检查定时发布是否超出可用时间
    time_str = data.get("发布时间", "")
    if time_str == "":
        print("未设置发布时间,默认为立即发布")
    target_time = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
    current_time = datetime.now()
    time_diff = target_time - current_time
    if not (time_diff.total_seconds() > 3600 and time_diff.days <= 14):
        raise ValueError("指定定时时间不在允许范围,允许范围为(1h-14天)")
    print("小红书.图文校验完成")
    pass


# 对知乎文章进行校验
def check_zhihu_wenzhang(data):
    # 1.对文本内容进行校验
    title = data.get("标题", "")
    desc = data.get("作品描述", "")
    if len(title) > 20:
        raise ValueError("标题最大20个字符")
    if len(desc) > 1000:
        raise ValueError("作品描述字数不大于1000")
    # 2.对文章封面进行校验
    cover = data.get("封面", "")
    if not os.path.isabs(cover) or not os.path.exists(cover):
        print(f"封面路径 {cover} 不存在或者没有设置封面")
    # 校验图片格式
    ALLOWED_FORMATS = ['jpeg', 'JPG', 'PNG']
    if not cover.lower().endswith(ALLOWED_FORMATS):
        raise ValueError(f"封面图片格式不符合要求，文件路径：{cover}")
    # 3.校验知乎文章话题
    topic = data.get("文章话题", "")
    topic_list = topic.split(',')
    if len(topic_list) > 3 or len(topic_list) == 0:
        raise ValueError("话题数量不能超过3个")
    print("知乎文章校验完成")


# 对微信文章进行校验
def check_winxin_tuwen(data):
    # 1对图片进行校验
    image_paths_str = data.get("媒体")
    # 将图片路径字符串分割为列表
    image_paths = image_paths_str.split(';')

    # 设定规则参数
    MAX_SIZE_MB = 10
    ALLOWED_FORMATS = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp')  # 不包含'.gif'
    # MAX_ASPECT_RATIO = 1 / 2
    MAX_IMAGE_COUNT = 20

    # 校验图片数量
    if len(image_paths) > MAX_IMAGE_COUNT:
        raise ValueError(f"图片数量超过最大限制，当前数量为{len(image_paths)}，最大允许数量为{MAX_IMAGE_COUNT}")

    # 遍历每个图片路径进行校验
    for image_path in image_paths:
        # 检查文件是否存在
        if not os.path.exists(image_path):
            print(f"{image_path}文件不存在")
        # 校验图片格式
        if not image_path.lower().endswith(ALLOWED_FORMATS):
            raise ValueError(f"图片格式不符合要求，文件路径：{image_path}")

        # 校验图片大小
        if os.path.getsize(image_path) > MAX_SIZE_MB * 1024 * 1024:
            raise ValueError(f"图片大小超过最大限制，文件路径：{image_path}")

        # 校验图片分辨率
        # with Image.open(image_path) as img:
        #     width, height = img.size
        #     if width / height > MAX_ASPECT_RATIO or height / width > MAX_ASPECT_RATIO:
        #         print(f"建议宽高比不超过1:2，文件路径：{image_path}")
    # 2.文本进行校验
    title = data.get("标题", "")
    desc = data.get("作品描述", "")
    if len(title) > 64:
        raise ValueError("标题最大20个字符")
    if len(title + desc) > 1000:
        raise ValueError("标题 + 作品描述字数不大于1000")
    # 3.快捷私信
    option_list = ["允许", "不允许"]
    quick_msg = data.get("快捷私信", " ")
    if quick_msg not in option_list:
        print("没有此选项,可选项为(允许, 不允许)，默认不允许")
    # 4.平台推荐
    option_list = ["允许", "不允许"]
    platform_rec = data.get("平台推荐", " ")
    if platform_rec not in option_list:
        print("没有此选项,可选项为(允许, 不允许)，默认不允许")
    print("微信图文校验结束")


# 对微信视频进行校验
def check_winxin_video(data):
    # 1.对微信视频进行校验
    video_path = data.get("媒体")
    # 检查文件是否存在
    if not os.path.exists(video_path):
        print(f"{video_path}文件不存在")
    # 支持的视频格式列表 H.264为avi后缀名
    supported_formats = ['mp4', 'avi']  # 更新支持的视频格式列表

    # 获取视频文件的扩展名
    file_extension = os.path.splitext(video_path)[1][1:].lower()

    # 检查视频格式是否支持
    if file_extension not in supported_formats:
        raise ValueError(f"视频格式不支持。推荐的格式有：{supported_formats}")

    # 获取视频文件的大小
    file_size = os.path.getsize(video_path)

    # 检查视频文件大小是否超过4GB
    if file_size > 4 * 1024 ** 3:
        raise ValueError("视频文件大小超过4GB。")

    # 使用moviepy获取视频属性
    clip = VideoFileClip(video_path)

    # 检查视频时长是否在15分钟以内
    if clip.duration > 120 * 60:
        raise ValueError("视频时长超过15分钟。")

    # 获取视频分辨率
    video_resolution = clip.size
    width, height = video_resolution

    # 检查视频分辨率是否为720p及以上
    if width < 720 or height < 1280:
        print("建议视频分辨率不低于720p，码率10Mbps以内")

    # 如果有额外的要求检查视频分辨率是否超过1080p，可以添加以下代码
    # 检查视频分辨率是否超过1080p，这部分代码仅作为参考，根据实际情况使用
    if width > 1920 or height > 1080:
        print("警告：超过1080P的视频建议用网页端上传以保证画质更清晰。")
    else:
        print("视频分辨率适中，适合上传。")

    print("视频校验通过：格式、大小、时长和分辨率均符合要求。")

    # 释放资源
    clip.close()
    # 2.对文本内容进行校验
    title = data.get("标题", "")
    desc = data.get("作品描述", "")
    if len(title) > 20:
        raise ValueError("标题最大20个字符")
    if len(title + desc) > 1000:
        raise ValueError("标题 + 作品描述字数不大于1000")
    # 3.检查位置
    location = data.get("位置", "")
    if location is None or location == "":
        print(f"没有设置位置")
    # 4.定时校验
    time_str = data.get("发布时间", "")
    if time_str == "":
        print("未设置发布时间,默认为立即发布")
    target_time = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
    current_time = datetime.now()
    time_diff = target_time - current_time
    if not (time_diff.days <= 30):
        raise ValueError("指定定时时间不在允许范围,允许范围为(当前时间-30天)")
    print("微信视频校验完成")


# 对数据格式进行校验
def rule_check(data: dict):
    platform, mtype = data.get("平台", ""), data.get("类型", "")
    platform_list = ["抖音", "小红书", "微信", "知乎"]
    if platform not in platform_list:
        raise ValueError("没有此平台或平台名称错误")
    # 抖音
    if platform == "抖音":
        mtype_list = ['图文', '视频']
        if mtype not in mtype_list:
            raise ValueError("没有此类型或类型名称错误")
        if mtype == "图文":
            check_douyin_tuwen(data)
        elif mtype == "视频":
            check_douyin_video(data)
        pass
    # 小红书
    elif platform == "小红书":
        mtype_list = ['图文', '视频']
        if mtype not in mtype_list:
            raise ValueError("没有此类型或类型名称错误")
        if mtype == "图文":
            check_xiaohonshu_tuwen(data)
        elif mtype == "视频":
            check_xiaohonshu_video(data)
        pass
    # 微信
    elif platform == "微信":
        mtype_list = ['图文', '视频']
        if mtype not in mtype_list:
            raise ValueError("没有此类型或类型名称错误")
        if mtype == "图文":
            check_winxin_tuwen(data)
        elif mtype == "视频":
            check_winxin_video(data)
        pass
    # 知乎
    elif platform == "知乎":
        mtype_list = ['文章']
        if mtype not in mtype_list:
            raise Exception("没有此类型或类型名称错误")
        if mtype == "文章":
            check_zhihu_wenzhang(data)
        pass


if __name__ == '__main__':
    values = {
        '平台': '小红书',
        '类型': '图文',
        '媒体': r"F:\.desktop\素材\1.png",
        '标题': '测试标题',
        '作品描述': '测试作品描述',
        '封面': r"F:\.desktop\素材\1.png",
        '音乐': '感恩的心',
        '位置': '长沙市',
        '申请关联热点': '',
        '允许他人保存图片': '',
        '权限设置': '',
        '发布时间': '2024-2-21 17:00',
    }
    rule_check(values)
